// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include "winsock2.h"
#include "Ws2spi.h"
#include "detours.h"

#pragma comment(lib,"detours.lib")

#pragma comment(lib,"detoured.lib")

#pragma comment(lib,"ws2_32.lib")

typedef int (* __pfnWSPStartup)(
  __in   WORD wVersionRequested,
  __out  LPWSPDATA lpWSPData,
  __in   LPWSAPROTOCOL_INFO lpProtocolInfo,
  __in   WSPUPCALLTABLE UpcallTable,
  __out  LPWSPPROC_TABLE lpProcTable
);

__pfnWSPStartup pfnWSPStartup;
WSPPROC_TABLE procTable;

int WSPAPI MyWSPCONNECT(
    SOCKET s,
    const struct sockaddr FAR * name,
    int namelen,
    LPWSABUF lpCallerData,
    LPWSABUF lpCalleeData,
    LPQOS lpSQOS,
    LPQOS lpGQOS,
    LPINT lpErrno
    )
{
	int port = htons(((sockaddr_in*)name)->sin_port);
	if(port!=1110)
	{
		*lpErrno=WSAETIMEDOUT;
		return SOCKET_ERROR;
	}
	return procTable.lpWSPConnect(s,name,namelen,lpCallerData,lpCalleeData,lpSQOS,lpGQOS,lpErrno);
}

int MyWSPStartup(
  __in   WORD wVersionRequested,
  __out  LPWSPDATA lpWSPData,
  __in   LPWSAPROTOCOL_INFO lpProtocolInfo,
  __in   WSPUPCALLTABLE UpcallTable,
  __out  LPWSPPROC_TABLE lpProcTable
)
{
	int ret= pfnWSPStartup(wVersionRequested,lpWSPData,lpProtocolInfo,UpcallTable,lpProcTable);
	procTable = *lpProcTable;
	lpProcTable->lpWSPConnect=MyWSPCONNECT;
	return ret;
}

void Hook(){
	HMODULE hmodule = LoadLibrary(__TEXT("MSWSOCK.dll"));
	pfnWSPStartup =(__pfnWSPStartup)GetProcAddress(hmodule,"WSPStartup");

	DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    DetourAttach(&(PVOID&)pfnWSPStartup, MyWSPStartup);
    DetourTransactionCommit();
}

void Unhook(){

	DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    DetourDetach(&(PVOID&)pfnWSPStartup, MyWSPStartup);
    DetourTransactionCommit();

	pfnWSPStartup=NULL;
}


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		Hook();
		break;
	case DLL_THREAD_ATTACH:
		break;
	case DLL_THREAD_DETACH:
		break;
	case DLL_PROCESS_DETACH:
		Unhook();
		break;
	}
	return TRUE;
}

